package com.pro.common.service.file.util;


import cn.hutool.core.util.IdUtil;
import com.pro.common.service.file.util.sub.UserFilePathParam;
import com.pro.common.service.file.util.sub.UserFilePathResult;

import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.*;

public class PathTemplateUtil {

    public static final String LOGICAL_PATH_PREFIX = "user-uploads/";

    // 时间格式化
    private static final java.time.format.DateTimeFormatter YYYY = java.time.format.DateTimeFormatter.ofPattern("yyyy");
    private static final java.time.format.DateTimeFormatter MM = java.time.format.DateTimeFormatter.ofPattern("MM");
    private static final java.time.format.DateTimeFormatter DD = java.time.format.DateTimeFormatter.ofPattern("dd");

    private PathTemplateUtil() {}
    // 禁止实例化
    public static UserFilePathResult buildPath(UserFilePathParam request) {
        if (request.getUserId() == null) {
            throw new IllegalArgumentException("userId 必填");
        }

        String uuid = request.getUuid() != null ? request.getUuid() : IdUtil.simpleUUID();

        // 处理文件名
        String fileName = generateFileName(request.getOriginalFilename(), uuid);

        Map<String, Object> params = new HashMap<>();
        params.put("module", request.getModuleName() != null ? request.getModuleName() : "default");
        params.put("userId", request.getUserId());
        params.put("batchId", request.getBatchId() != null ? request.getBatchId() : "");
        params.put("fileName", fileName);
        params.put("moduleNameTranslate", request.getModuleNameTranslate());

        String physical = resolve(request.getTemplatePhysical(), params);
        String logical = resolve(request.getTemplateLogical(), params);

        // 计算 nodeName 和 ancestorPath
        String[] parts = logical.split("/");
        List<String> pathParts = Arrays.stream(parts).filter(p -> !p.isBlank()).toList();
        String nodeName = pathParts.isEmpty() ? "" : pathParts.get(pathParts.size() - 1);
        String ancestorPath = pathParts.size() <= 1 ? "/" : "/" + String.join("/", pathParts.subList(0, pathParts.size() - 1)) + "/";

        String url = request.getUrl();

//        String fileName = result.getFileName(); // uuid_xxx.png
        String extension = "";
        int dotIndex = fileName.lastIndexOf('.');
        if (dotIndex >= 0 && dotIndex < fileName.length() - 1) {
            extension = fileName.substring(dotIndex + 1).toLowerCase(); // png
        }
        long sizeBytes = getFileSizeByUrl(url);
        String contentType = URLConnection.guessContentTypeFromName("file." + extension);
        return UserFilePathResult.builder()
                .physicalPath(physical)
                .logicalPath(logical)
                .ancestorPath(ancestorPath)
                .nodeName(nodeName)
                .fileName(fileName)
                .extension(extension)
                .sizeBytes(sizeBytes)
                .contentType(contentType)
                .build();
    }

    public static long getFileSizeByUrl(String fileUrl) {
        try {
            URL url = new URL(fileUrl);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("HEAD");
            conn.connect();
            int code = conn.getResponseCode();
            if (code >= 200 && code < 300) {
                String length = conn.getHeaderField("Content-Length");
                if (length != null) {
                    return Long.parseLong(length);
                }
            }
        } catch (Exception e) {
            // 日志打印或忽略
            e.printStackTrace();
        }
        return 0; // 无法获取
    }

    public static String generateFileName(String originalFilename, String uuid) {
        if (originalFilename == null || originalFilename.isBlank()) {
            return uuid;
        }

        String ext = "";
        String baseName = originalFilename;

        int dotIndex = originalFilename.lastIndexOf('.');
        if (dotIndex >= 0) {
            baseName = originalFilename.substring(0, dotIndex);
            ext = originalFilename.substring(dotIndex); // 保留扩展名
        }

        // 裁剪文件名长度，保证 URL 简短
        if (baseName.length() > 20) {
            baseName = baseName.substring(0, 20);
        }

        // 最终文件名 = uuid_短文件名 + 扩展名
        return uuid + "_" + baseName + ext;
    }


    private static String resolve(String template, Map<String, Object> params) {
        if (template == null) return null;

        java.time.LocalDateTime now = java.time.LocalDateTime.now();

        template = template
                .replace("{yyyy}", YYYY.format(now))
                .replace("{MM}", MM.format(now))
                .replace("{dd}", DD.format(now));

        for (Map.Entry<String, Object> entry : params.entrySet()) {
            String key = entry.getKey();
            Object val = entry.getValue();
            template = template.replace("{" + key + "}", val != null ? val.toString() : "");
        }

        // 移除未替换占位符
        template = template.replaceAll("\\{[^}]+}", "");

        // 路径规范化
        if (!template.startsWith("/")) template = "/" + template;
//        if (!template.endsWith("/")) template = template + "/";
        template = template.replaceAll("//+", "/");

        return template;
    }
    public static void main(String[] args) {
        // 模拟请求参数
        UserFilePathParam param = new UserFilePathParam();
        param.setUserId(12345L);
//        param.setBatchId("67890");
        param.setModuleName("images");
        param.setOriginalFilename("report.pdf");
        param.setTemplatePhysical("/{module}/{userId}/{yyyy}/{MM}/{dd}/{batchId}/{fileName}");
        param.setTemplateLogical("/documents/work/{fileName}");

        // 执行
        UserFilePathResult result = PathTemplateUtil.buildPath(param);

        // 打印结果
        System.out.println("physicalPath = " + result.getPhysicalPath());
        System.out.println("logicalPath  = " + result.getLogicalPath());
        System.out.println("ancestorPath = " + result.getAncestorPath());
        System.out.println("nodeName     = " + result.getNodeName());
        System.out.println("fileName     = " + result.getFileName());
        System.out.println("extension    = " + result.getExtension());
        System.out.println("contentType  = " + result.getContentType());
        System.out.println("sizeBytes    = " + result.getSizeBytes());
    }
}
